/*
 * Copyright 2007-2008 by Matthias Buch-Kromann <mbk.isv@cbs.dk>.
 * 
 * This file is part of the Open-source Dependency Toolkit (OSDT),
 * see http://code.google.com/p/open-source-dependency-toolkit. 
 * 
 * The OSDT is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * The OSDT is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with the OSDT in the file COPYING and COPYING.LESSER. If not, see
 * http://www.gnu.org/licenses.
 */


package org.osdtsystem.graphs;

import org.osdtsystem.exceptions.EdgeNotFoundException;
import org.osdtsystem.graphs.views.View;
import org.osdtsystem.values.NodeID;
import org.osdtsystem.values.Location;
import org.osdtsystem.values.Layer;
import org.osdtsystem.values.Feature;
import org.osdtsystem.values.EdgeID;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.osdtsystem.values.StringFeature;

/**
 * An abstract graph with methods shared by all graphs.
 * @author Matthias Buch-Kromann <mbk.isv@cbs.dk>
 */
public abstract class AbstractGraph implements Graph {
    @Override
    public List<NodeID> nodes(Layer layer) {
        final List<NodeID> list = new ArrayList();
        for (NodeID node : nodes())
            if (nodeLayer(node).equals(layer))
                list.add(node);
            return Arrays.asList(list.toArray(new NodeID[0]));
    }
    
    @Override
    public List<EdgeID> edges(final NodeID node) {
        final Set<EdgeID> set = new HashSet<EdgeID>(outEdges(node));
        set.addAll(inEdges(node));
        return Arrays.asList(set.toArray(new EdgeID[0]));
    }

    @Override
    public List<EdgeID> edges(final NodeID node, final Layer layer) {
        final Set<EdgeID> set = new HashSet<EdgeID>(outEdges(node, layer));
        set.addAll(inEdges(node, layer));
        return Arrays.asList(set.toArray(new EdgeID[0]));
    }

    @Override
    public List<EdgeID> edges(Layer layer) {
        // Return empty list if layer is null
        if (layer == null) 
            return Collections.emptyList();
        
        // Otherwise build list
        final List<EdgeID> list = new ArrayList<EdgeID>();
        for (EdgeID edge : edges())
            if (layer.equals(edgeLayer(edge)))
                list.add(edge);
        return Arrays.asList(list.toArray(new EdgeID[0]));        
    }

    @Override
    public List<EdgeID> inEdges(final NodeID node, final Layer layer) {
        // Return empty list if layer or node is null
        if (layer == null || node == null)
            return Collections.emptyList();
        
        // Otherwise build list
        final List<EdgeID> list = new ArrayList<EdgeID>();
        for (EdgeID edge : inEdges(node))
            if (layer.equals(edgeLayer(edge)))
                list.add(edge);
        return Arrays.asList(list.toArray(new EdgeID[0]));
    }

    @Override
    public List<EdgeID> outEdges(final NodeID node, final Layer layer) {
        // Return empty list if layer is null
        if (layer == null || node == null)
            return Collections.emptyList();
        
        // Otherwise build list
        final List<EdgeID> list = new ArrayList<EdgeID>();
        for (EdgeID edge : outEdges(node))
            if (layer.equals(edgeLayer(edge)))
                list.add(edge);
        return Arrays.asList(list.toArray(new EdgeID[0]));
    }
   
    @Override
    public List<Feature> features(Location loc) {
        return features(loc, false);
    }

    @Override
    public List<Feature> features(Location loc, final boolean includeInternalFeatures) {
        return features(layer(loc), includeInternalFeatures);
    }
    
    public void commit() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void clear(Layer layer) {
        // Remove all edges in the layer
        for (EdgeID e : edges(layer))
            removeEdge(e);
        
        // Remove all nodes in the layer
        for (NodeID n : nodes(layer))
            removeNode(n);
    }

    @Override
    public final View view(String uniqueName) {
        return view(viewID(uniqueName));
    }

    
}
